import { _decorator, Component, find, instantiate, Node, NodePool, Prefab, Vec3 } from 'cc';
import { NodeController } from './NodeController';
import { GameManager } from './GameManager';
import { MoveOrEatManager } from './MoveOrEatManager';
import { PieceManagerBase } from './PieceManagerBase';
const { ccclass, property } = _decorator;

@ccclass('QipanController')
export class QipanController extends Component {
    private static _instance: QipanController | null = null;
    gameManager: GameManager;
    public static getInstance(): QipanController {
        if (!this._instance) {
            this._instance = new QipanController();
        }
        return this._instance;
    }
    start() {
        this.gameManager = find('Canvas/GameManager').getComponent(GameManager);
    }
    getEnemyNode(enemyPosX: number, enemyPosY: number): Node {
        let childrenName = `Node${9 - enemyPosX}${10 - enemyPosY}`;
        return this.node.getChildByName(childrenName);
    }
    getNode(x: number, y: number): Node {
        let childrenName = `Node${x}${y}`;
        const node = this.node.getChildByName(childrenName);
        return node;
    }
    addMoveNode(posX: number, posY: number, targetNode: PieceManagerBase, piece: Node) {
        console.log('can move:(' + posX + ',' + posY + ')');

        const allowNode = this.gameManager.getAllowNode();
        allowNode.setPosition(piece.getPosition());
        allowNode.active = true;
        let moveOrEatManager = allowNode.getComponent(MoveOrEatManager);
        moveOrEatManager.posX = posX;
        moveOrEatManager.posY = posY;
        this.gameManager.moveList.push(allowNode);
        moveOrEatManager.targetNode = targetNode;
    }
    addAttackNode(posX: number, posY: number, targetNode: PieceManagerBase, piece: Node) {
        console.log('can attack:(' + posX + ',' + posY + ')');
        const attackNode = this.gameManager.getAttackNode();
        attackNode.setPosition(piece.getPosition());
        attackNode.active = true;
        attackNode.setSiblingIndex(piece.getSiblingIndex());
        let moveOrEatManager = attackNode.getComponent(MoveOrEatManager);
        moveOrEatManager.posX = posX;
        moveOrEatManager.posY = posY;
        this.gameManager.attackList.push(attackNode);
        moveOrEatManager.targetNode = targetNode;
    }
    /**
     * 获取直线移动的节点
     * @param targetNode 目标节点
     * @param step 步长
     * @param isSingleDirection 是否单行
     * @param enableBack 是否允许后退
     * @param limit 限制范围 [上，下，左，右]
     * @returns 
     */
    canLineMoveOrAttck(targetNode: PieceManagerBase, step: number, isSingleDirection: boolean = false, enableBack: boolean = true, limit: number[] = [9, 0, 0, 8], enableSkip: boolean = false): Promise<boolean> {
        return new Promise((resolve, reject) => {
            let x = targetNode.posX;
            let y = targetNode.posY;
            let skipCount = 0;
            const xMoveEnd = x + step > limit[3] ? limit[3] : x + step;
            const yMoveEnd = y + step > limit[0] ? limit[0] : y + step;
            const xMoveStart = x - step < limit[2] ? limit[2] : x - step;
            const yMoveStart = y - step < limit[1] ? limit[1] : y - step;
            // console.log('xMoveStart:'+xMoveStart+' yMoveStart:'+yMoveStart+' xMoveEnd:'+xMoveEnd+' yMoveEnd:'+yMoveEnd);
            for (let i = y; i <= yMoveEnd; i++) {
                if (i == y) continue;
                const piece = this.getNode(x, i);
                if (!piece.getComponent(NodeController).isOwned) {
                    if (skipCount < 1) {
                        this.addMoveNode(x, i, targetNode, piece);
                    }
                    // this.addMoveNode(x, i, targetNode, piece);
                } else {
                    if (enableSkip && skipCount++ < 1) {
                        continue;
                    }
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x, i, targetNode, piece);
                    }
                    break;
                }
            }
            if (isSingleDirection) return resolve(true);
            skipCount = 0;
            for (let i = x; i >= xMoveStart; i--) {
                if (i == x) continue;
                const piece = this.getNode(i, y);
                if (!piece.getComponent(NodeController).isOwned) {
                    if (skipCount < 1) {
                        this.addMoveNode(i, y, targetNode, piece);
                    }

                } else {
                    if (enableSkip && skipCount++ < 1) {
                        continue;
                    }
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(i, y, targetNode, piece);
                    }
                    break;
                }
            }
            skipCount = 0;
            for (let i = x; i <= xMoveEnd; i++) {
                if (i == x) continue;
                const piece = this.getNode(i, y);
                if (!piece.getComponent(NodeController).isOwned) {
                    if (skipCount < 1) {
                        this.addMoveNode(i, y, targetNode, piece);
                    }
                } else {
                    if (enableSkip && skipCount++ < 1) {
                        continue;
                    }
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(i, y, targetNode, piece);
                    }
                    break;
                }
            }
            if (!enableBack) return resolve(true);
            skipCount = 0;
            for (let i = y; i >= yMoveStart; i--) {
                if (i == y) continue;
                const piece = this.getNode(x, i);
                if (!piece.getComponent(NodeController).isOwned) {
                    if (skipCount < 1) {
                        this.addMoveNode(x, i, targetNode, piece);
                    }
                } else {
                    if (enableSkip && skipCount++ < 1) {
                        continue;
                    }
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x, i, targetNode, piece);
                    }
                    break;
                }
            }
            resolve(true);
        })
    }
    /**
     * 获取斜线移动的节点
     * @param targetNode 目标节点
     * @param step 步长
     * @param skip 跳过步数
     * @param limit 限制范围 [上，下，左，右]
     * @returns 
     */
    canDiagonalMoveOrAttck(targetNode: PieceManagerBase, step: number, limit: number[] = [9, 0, 0, 8]): Promise<boolean> {
        return new Promise((resolve, reject) => {
            let x = targetNode.posX;
            let y = targetNode.posY;
            const xMoveEnd = x + step > limit[3] ? limit[3] : x + step;
            const yMoveEnd = y + step > limit[0] ? limit[0] : y + step;
            const xMoveStart = x - step < limit[2] ? limit[2] : x - step;
            const yMoveStart = y - step < limit[1] ? limit[1] : y - step;
            // 右上对角线遍历
            for (let i = 1; i <= step && x + i <= xMoveEnd && y - i >= yMoveStart; i++) {
                const piece = this.getNode(x + i, y - i);
                if (!piece || !piece.getComponent(NodeController).isOwned) {
                    this.addMoveNode(x + i, y - i, targetNode, piece)
                } else {
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x + i, y - i, targetNode, piece);
                    }
                    break;
                }
            }
            // 左下对角线遍历
            for (let i = 1; i <= step && x - i >= xMoveStart && y + i <= yMoveEnd; i++) {
                const piece = this.getNode(x - i, y + i);
                if (!piece || !piece.getComponent(NodeController).isOwned) {
                    this.addMoveNode(x - i, y + i, targetNode, piece)
                } else {
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x - i, y + i, targetNode, piece);
                    }
                    break;
                }
            }
            // 左上对角线遍历
            for (let i = 1; i <= step && x - i >= xMoveStart && y - i >= yMoveStart; i++) {
                const piece = this.getNode(x - i, y - i);
                if (!piece || !piece.getComponent(NodeController).isOwned) {
                    this.addMoveNode(x - i, y - i, targetNode, piece)
                } else {
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x - i, y - i, targetNode, piece);
                    }
                    break;
                }
            }
            // 右下对角线遍历
            for (let i = 1; i <= step && x + i <= xMoveEnd && y + i <= yMoveEnd; i++) {
                const piece = this.getNode(x + i, y + i);
                if (!piece || !piece.getComponent(NodeController).isOwned) {
                    this.addMoveNode(x + i, y + i, targetNode, piece)
                } else {
                    if (piece.getComponent(NodeController).owner.isEnemy) {
                        this.addAttackNode(x + i, y + i, targetNode, piece);
                    }
                    break;
                }
            }
            resolve(true);
        });
    }

    canRangeMoveOrAttck(targetNode: PieceManagerBase, range: number[] = [1, 1], enableObstruct: boolean = false, limit: number[] = [9, 0, 0, 8]): Promise<boolean> {
        return new Promise((resolve, reject) => {
            const judgeObstruct = (x0: number, y0: number, dxVal: number, dyVal: number) => {
                let deltaX = parseInt(dxVal / 2 + '');
                let deltaY = parseInt(dyVal / 2 + '');
                let deltaNode = this.getNode(x0 + deltaX, y0 + deltaY)
                return deltaNode.getComponent(NodeController).isOwned
            }
            const generatePoints = (x0: number, y0: number): boolean => {
                let dx = [range[0], range[1], -range[0], -range[1]];
                let dy = [range[0], range[1], -range[0], -range[1]];
                if (range[0] === range[1]) {
                    dx = [range[0],-range[0]];
                    dy = [range[1], -range[1]];
                }
                

                // 遍历每种步长组合
                for (const dxVal of dx) {
                    for (const dyVal of dy) {
                        if (Math.abs(dxVal) + Math.abs(dyVal) === range[0] + range[1]) {
                            if (x0 + dxVal < limit[2] || x0 + dxVal > limit[3] || y0 + dyVal < limit[1] || y0 + dyVal > limit[0]) continue;
                            const piece = this.getNode(x0 + dxVal, y0 + dyVal)
                            if (!piece || !piece.getComponent(NodeController).isOwned) {
                                if (enableObstruct && judgeObstruct(x0, y0, dxVal, dyVal)) continue;
                                this.addMoveNode(x0 + dxVal, y0 + dyVal, targetNode, piece)
                            } else {
                                if (piece.getComponent(NodeController).owner.isEnemy) {
                                    if (enableObstruct && judgeObstruct(x0, y0, dxVal, dyVal)) continue;
                                    this.addAttackNode(x0 + dxVal, y0 + dyVal, targetNode, piece);
                                }
                                continue;
                            }
                        }
                    }
                }
                return true
            }
            let x = targetNode.posX;
            let y = targetNode.posY;
            resolve(generatePoints(x, y))

        });
    }



    update(deltaTime: number) {

    }
}

